home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmigaPlus / Tools / Development / renderlib40 / src / rnd_histogram.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-21  |  7.9 KB  |  431 lines

  1.  
  2. #include "lib_init.h"
  3. #include "lib_debug.h"
  4. #include <render/render.h>
  5. #include <proto/utility.h>
  6. #include <proto/exec.h>
  7.  
  8.  
  9. /************************************************************************** 
  10. **
  11. **    createhistogram
  12. */
  13.  
  14. LIBAPI RNDHISTO *CreateHistogramA(struct TagItem *tags)
  15. {
  16.     APTR rmh;
  17.     RNDHISTO *h;
  18.     UWORD type;
  19.     
  20.     type = (UWORD) GetTagData(RND_HSType, HSTYPE_15BIT_TURBO, tags);
  21.     switch (type)
  22.     {
  23.         case HSTYPE_12BIT:
  24.         case HSTYPE_15BIT:
  25.         case HSTYPE_18BIT:
  26.         case HSTYPE_21BIT:
  27.         case HSTYPE_24BIT:
  28.             break;
  29.  
  30.         case HSTYPE_12BIT_TURBO:
  31.         case HSTYPE_15BIT_TURBO:
  32.         case HSTYPE_18BIT_TURBO:
  33.             type &= HSTYPE_MASK;        /* turbo currently not supported */
  34.             break;
  35.  
  36.         default:
  37.             return NULL;
  38.     }
  39.  
  40.     rmh = (APTR) GetTagData(RND_RMHandler, NULL, tags);
  41.     h = AllocRenderVecClear(rmh, sizeof(RNDHISTO));
  42.     if (h)
  43.     {
  44.         ULONG mask;
  45.         InitSemaphore(&h->lock);
  46.         h->type = type;
  47.         h->rmh = rmh;
  48.         h->bitspergun = type & HSTYPE_MASK;
  49.         mask = (0xff << (8 - h->bitspergun)) & 0xff;
  50.         h->rgbmask = (mask << 16) | (mask << 8) | mask;
  51.     }
  52.     return h;
  53. }
  54.  
  55.  
  56. /************************************************************************** 
  57. **
  58. **    deletehistogram
  59. */
  60.  
  61. LIBAPI void DeleteHistogram(RNDHISTO *h)
  62. {
  63.     if (h)
  64.     {
  65.         struct RNDTreeMemBlock *node, *nextnode;
  66.     
  67.         node = h->memlist;
  68.         while (node)
  69.         {
  70.             nextnode = node->next;
  71.             FreeRenderMem(h->rmh, node, sizeof(struct RNDTreeMemBlock));
  72.             node = nextnode;
  73.         }
  74.     
  75.         FreeRenderVec((ULONG *) h);
  76.     }
  77. }
  78.  
  79.  
  80. /************************************************************************** 
  81. **
  82. **    queryhistogram
  83. */
  84.  
  85. LIBAPI ULONG QueryHistogram(RNDHISTO *h, Tag tag)
  86. {
  87.     ULONG result = 0xffffffff;
  88.     switch (tag)
  89.     {
  90.         case RND_NumColors:
  91.             result = h->numcolors;
  92.             break;
  93.         case RND_NumPixels:
  94.             result = h->numpixels;
  95.             break;
  96.         case RND_RMHandler:
  97.             result = (ULONG) h->rmh;
  98.             break;
  99.         case RND_HSType:
  100.             result = (ULONG) h->type;
  101.             break;
  102.     }
  103.     return result;
  104. }
  105.  
  106.  
  107.  
  108. /* 
  109. **    tree histogram
  110. */
  111.  
  112. static struct RNDTreeNode *alloctreenode(RNDHISTO *h)
  113. {
  114.     struct RNDTreeMemBlock *mn = h->memlist;
  115.  
  116.     if (mn)
  117.     {
  118.         if (mn->free)
  119.         {
  120.             return mn->nodes + --mn->free;
  121.         }
  122.     }
  123.  
  124.     mn = AllocRenderMem(h->rmh, sizeof(struct RNDTreeMemBlock));
  125.     if (mn)
  126.     {
  127.         mn->next = h->memlist;
  128.         h->memlist = mn;
  129.         mn->free = RNDTREEMEMBLOCK_NUMNODES - 1;
  130.         return mn->nodes + RNDTREEMEMBLOCK_NUMNODES - 1;
  131.     }
  132.     
  133.     return NULL;
  134. }
  135.  
  136.  
  137. static LONG addrgb_tree(RNDHISTO *h, ULONG rgb, ULONG count)
  138. {
  139.     struct RNDTreeNode **nodeptr = &h->root;
  140.     struct RNDTreeNode *node;
  141.  
  142.     ULONG rgbmask = h->rgbmask;    
  143.     ULONG chkmask = 0x800000;
  144.     
  145.     rgb &= rgbmask;
  146.  
  147.     while (node = *nodeptr)
  148.     {
  149.         if (node->entry.rgb == rgb)
  150.         {
  151.             node->entry.count += count;
  152.             h->numpixels += count;
  153.             return ADDH_SUCCESS;
  154.         }
  155.  
  156.         while (!(chkmask & rgbmask)) chkmask >>= 1;
  157.     
  158.         if (rgb & chkmask)
  159.         {
  160.             nodeptr = &node->left;
  161.         }
  162.         else
  163.         {
  164.             nodeptr = &node->right;
  165.         }
  166.  
  167.         chkmask >>= 1;
  168.     }
  169.  
  170.     node = alloctreenode(h);
  171.     if (node)
  172.     {
  173.         *nodeptr = node;
  174.         node->left = NULL;
  175.         node->right = NULL;
  176.         node->entry.rgb = rgb;
  177.         node->entry.count = count;
  178.         h->numpixels += count;
  179.         h->numcolors++;
  180.         return ADDH_SUCCESS;
  181.     }
  182.     
  183.     return ADDH_NOT_ENOUGH_MEMORY;
  184. }
  185.  
  186.  
  187. /************************************************************************** 
  188. **
  189. **    addrgb
  190. */
  191.  
  192. LIBAPI ULONG AddRGB(RNDHISTO *h, ULONG rgb, ULONG count)
  193. {
  194.     ULONG result = ADDH_NO_DATA;
  195.     if (h && count)
  196.     {
  197.         ObtainSemaphore(&h->lock);
  198.         result = addrgb_tree(h, rgb, count);
  199.         ReleaseSemaphore(&h->lock);
  200.     }
  201.     return result;
  202. }
  203.  
  204. /************************************************************************** 
  205. **
  206. **    addrgbimage
  207. */
  208.  
  209. LIBAPI ULONG AddRGBImageA(RNDHISTO *h, ULONG *rgb, UWORD width, UWORD height, struct TagItem *tags)
  210. {
  211.     ULONG result = ADDH_NO_DATA;
  212.     if (h && rgb && width && height)
  213.     {
  214.         struct RND_ProgressMessage progmsg;
  215.         struct Hook *proghook = (struct Hook *) GetTagData(RND_ProgressHook, NULL, tags);
  216.         UWORD totw = (UWORD) GetTagData(RND_SourceWidth, width, tags);
  217.         UWORD y, x;
  218.  
  219.         progmsg.RND_PMsg_type = PMSGTYPE_LINES_ADDED;
  220.         progmsg.RND_PMsg_total = height;
  221.  
  222.         ObtainSemaphore(&h->lock);
  223.     
  224.         for (y = 0; y < height; ++y)
  225.         {
  226.             for (x = 0; x < width; ++x)
  227.             {
  228.                 result = addrgb_tree(h, *rgb++, 1);
  229.                 if (result != ADDH_SUCCESS) goto fail;
  230.             }
  231.  
  232.             if (proghook)
  233.             {
  234.                 progmsg.RND_PMsg_count = y;
  235.                 if (!CallHookPkt(proghook, h, &progmsg))
  236.                 {
  237.                     result = ADDH_CALLBACK_ABORTED;
  238.                     goto fail;
  239.                 }
  240.             }
  241.             
  242.             rgb += totw - width;
  243.         }            
  244. fail:
  245.         ReleaseSemaphore(&h->lock);
  246.     }
  247.     return result;
  248. }
  249.  
  250.  
  251. /************************************************************************** 
  252. **
  253. **    addchunkyimage
  254. */
  255.  
  256. LIBAPI ULONG AddChunkyImageA(RNDHISTO *h, UBYTE *chunky, 
  257.     UWORD width, UWORD height, RNDPAL *p, struct TagItem *tags)
  258. {
  259.     ULONG result = ADDH_NO_DATA;
  260.     if (h && p && chunky && width && height)
  261.     {
  262.         struct RND_ProgressMessage progmsg;
  263.         struct Hook *proghook = (struct Hook *) GetTagData(RND_ProgressHook, NULL, tags);
  264.         UWORD totw = (UWORD) GetTagData(RND_SourceWidth, width, tags);
  265.         UWORD y, x;
  266.  
  267.         progmsg.RND_PMsg_type = PMSGTYPE_LINES_ADDED;
  268.         progmsg.RND_PMsg_total = height;
  269.  
  270.         ObtainSemaphore(&h->lock);
  271.     
  272.         for (y = 0; y < height; ++y)
  273.         {
  274.             for (x = 0; x < width; ++x)
  275.             {
  276.                 result = addrgb_tree(h, p->table[*chunky++], 1);
  277.                 if (result != ADDH_SUCCESS) goto fail;
  278.             }
  279.  
  280.             if (proghook)
  281.             {
  282.                 progmsg.RND_PMsg_count = y;
  283.                 if (!CallHookPkt(proghook, h, &progmsg))
  284.                 {
  285.                     result = ADDH_CALLBACK_ABORTED;
  286.                     goto fail;
  287.                 }
  288.             }
  289.  
  290.             chunky += totw - width;
  291.         }            
  292. fail:
  293.         ReleaseSemaphore(&h->lock);
  294.     }
  295.     return result;
  296. }
  297.  
  298.  
  299. /************************************************************************** 
  300. **
  301. **    createhistogrampointerarray
  302. */
  303.  
  304. static struct RNDHistoEntry **scantree(struct RNDTreeNode *node, struct RNDHistoEntry **destp)
  305. {
  306.     if (node->left) destp = scantree(node->left, destp);
  307.     if (node->right) destp = scantree(node->right, destp);
  308.     *destp++ = &node->entry;
  309.     return destp;
  310. }
  311.  
  312. LIBAPI struct RNDHistoEntry **CreateHistogramPointerArray(RNDHISTO *h)
  313. {
  314.     struct RNDHistoEntry **array = NULL;
  315.     ULONG numcolors;
  316.     ObtainSemaphoreShared(&h->lock);
  317.     numcolors = QueryHistogram(h, RND_NumColors);    
  318.     if (numcolors > 0 && numcolors != 0xffffffff)
  319.     {
  320.         array = AllocRenderVec(h->rmh, numcolors * sizeof(struct RNDHistoEntry *));
  321.         if (array)
  322.         {
  323.             scantree(h->root, array);
  324.         }
  325.     }
  326.     ReleaseSemaphore(&h->lock);
  327.     return array;
  328. }
  329.  
  330.  
  331. /************************************************************************** 
  332. **
  333. **    countrgb
  334. */
  335.  
  336. static ULONG findrgb_tree(RNDHISTO *h, ULONG rgb)
  337. {
  338.     struct RNDTreeNode *node = h->root;
  339.  
  340.     ULONG rgbmask = h->rgbmask;    
  341.     ULONG chkmask = 0x800000;
  342.  
  343.     rgb &= rgbmask;
  344.     
  345.     while (node)
  346.     {
  347.         if (node->entry.rgb == rgb)
  348.         {
  349.             return (ULONG) node->entry.count;
  350.         }
  351.  
  352.         while (!(chkmask & rgbmask)) chkmask >>= 1;
  353.         
  354.         if (rgb & chkmask)
  355.         {
  356.             node = node->left;
  357.         }
  358.         else
  359.         {
  360.             node = node->right;
  361.         }
  362.         
  363.         chkmask >>= 1;
  364.     }
  365.     
  366.     return 0;
  367. }
  368.  
  369. LIBAPI ULONG CountRGB(RNDHISTO *h, ULONG rgb)
  370. {
  371.     ULONG result;
  372.     ObtainSemaphoreShared(&h->lock);
  373.     result = findrgb_tree(h, rgb);
  374.     ReleaseSemaphore(&h->lock);
  375.     return result;
  376. }
  377.  
  378.  
  379. /************************************************************************** 
  380. **
  381. **    counthistogram
  382. */
  383.  
  384. LIBAPI ULONG CountHistogram(RNDHISTO *h)
  385. {
  386.     return h->numcolors;
  387. }
  388.  
  389.  
  390. /************************************************************************** 
  391. **
  392. **    addhistogram
  393. */
  394.  
  395. static ULONG addtree(struct RNDTreeNode *node, RNDHISTO *dest, ULONG weight)
  396. {
  397.     ULONG result = ADDH_SUCCESS;
  398.  
  399.     if (node->left)
  400.     {
  401.         result = addtree(node->left, dest, weight);
  402.     }
  403.  
  404.     if (result == ADDH_SUCCESS)
  405.     {
  406.         if (node->right) result = addtree(node->right, dest, weight);
  407.     }
  408.     
  409.     if (result == ADDH_SUCCESS)
  410.     {
  411.         result = addrgb_tree(dest, node->entry.rgb, node->entry.count * weight);
  412.     }
  413.  
  414.     return result;
  415. }
  416.  
  417. LIBAPI ULONG AddHistogramA(RNDHISTO *dst, RNDHISTO *src, struct TagItem *tags)
  418. {
  419.     ULONG result = ADDH_NO_DATA;
  420.     if (dst && src)
  421.     {
  422.         ULONG weight = GetTagData(RND_Weight, 1, tags);
  423.         ObtainSemaphoreShared(&src->lock);
  424.         ObtainSemaphore(&dst->lock);
  425.         result = addtree(src->root, dst, weight);
  426.         ReleaseSemaphore(&dst->lock);
  427.         ReleaseSemaphore(&src->lock);
  428.     }
  429.     return result;
  430. }
  431.